package com.cit.draw.redis;

import org.apache.commons.pool.BasePoolableObjectFactory;
import org.apache.commons.pool.impl.GenericObjectPool;
import redis.clients.jedis.BinaryJedis;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Protocol;
import redis.clients.util.Pool;

/**
 * @author gutzeit
 * @since 6/3/12 10:24 AM
 */
public class BinaryJedisPool extends Pool<BinaryJedis> {
	

	public BinaryJedisPool(){
		this("0.0.0.0", 65535);
	}
	
  public BinaryJedisPool(final GenericObjectPool.Config poolConfig,
                         final String host) {
    this(poolConfig, host, Protocol.DEFAULT_PORT, Protocol.DEFAULT_TIMEOUT,
        null);
  }

  public BinaryJedisPool(String host, int port) {
    super(new GenericObjectPool.Config(), new BinaryJedisFactory(host, port,
        Protocol.DEFAULT_TIMEOUT, null));
  }

  public BinaryJedisPool(final GenericObjectPool.Config poolConfig, final String host, int port,
                         int timeout, final String password) {
    super(poolConfig, new BinaryJedisFactory(host, port, timeout, password));
  }

  public BinaryJedisPool(final GenericObjectPool.Config poolConfig,
                         final String host, final int port) {
    this(poolConfig, host, port, Protocol.DEFAULT_TIMEOUT, null);
  }

  public BinaryJedisPool(final GenericObjectPool.Config poolConfig,
                         final String host, final int port, final int timeout) {
    this(poolConfig, host, port, timeout, null);
  }

  /**
   * PoolableObjectFactory custom impl.
   */
  private static class BinaryJedisFactory extends BasePoolableObjectFactory {
    private final String host;
    private final int port;
    private final int timeout;
    private final String password;

    public BinaryJedisFactory(final String host, final int port,
                              final int timeout, final String password) {
      super();
      this.host = host;
      this.port = port;
      this.timeout = (timeout > 0) ? timeout : -1;
      this.password = password;
    }

    public Object makeObject() throws Exception {
      final BinaryJedis jedis;
      if (timeout > 0) {
        jedis = new Jedis(this.host, this.port, this.timeout);
      } else {
        jedis = new Jedis(this.host, this.port);
      }

      jedis.connect();
      if (null != this.password) {
        jedis.auth(this.password);
      }
      return jedis;
    }

    public void destroyObject(final Object obj) throws Exception {
      if (obj instanceof BinaryJedis) {
        final BinaryJedis jedis = (BinaryJedis) obj;
        if (jedis.isConnected()) {
          try {
            try {
              jedis.quit();
            } catch (Exception e) {
            }
            jedis.disconnect();
          } catch (Exception e) {

          }
        }
      }
    }

    public boolean validateObject(final Object obj) {
      if (obj instanceof BinaryJedis) {
        final BinaryJedis jedis = (BinaryJedis) obj;
        try {
          return jedis.isConnected() && jedis.ping().equals("PONG");
        } catch (final Exception e) {
          return false;
        }
      } else {
        return false;
      }
    }

  }
}

